package edu.uoc.tdp.pac4.server.connexiomanteniment.db;

import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.Vector;
import java.text.SimpleDateFormat;

import edu.uoc.tdp.pac4.server.connexiomanteniment.exceptions.*;
import edu.uoc.tdp.pac4.connexiomanteniment.*;
import edu.uoc.tdp.pac4.beans.Estudiante;


public class GestorUsuari extends Gestor {
	public GestorUsuari() {}
	
	public Usuari getUsuari(String login) throws ExceptionServer {
	 	Statement st = null; ResultSet rs = null; Usuari u = null;
		connect();
		try {
			// Mirant les unique constrains del model de dades podem confirmar que el login ha de ser unic, no hi ha dis usuaris amb el mateix id
  		    String query = "SELECT count(*) FROM usuari WHERE idusuari = '" + login + "'";
		 	st = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
		 	rs = st.executeQuery(query);	
			if (rs.next()) {
	 			if (rs.getInt(1) == 0) throw new ExceptionServer(ExceptionServer.SERVER_DB_USER_NOT_EXIST);
	 		} else throw new ExceptionServer(ExceptionServer.SERVER_DB_UNEXPECTED_ERROR);	 		
	 		// esbrinem el tipus d'usuari que es
	 		query = "SELECT tipususuari FROM usuari WHERE idusuari = '" + login + "'";
		 	rs = st.executeQuery(query);	
	 		if (rs.next()) {
	 			char role = rs.getString(1).charAt(0);
		 		if (role == Usuari.TIPUS_USUARI_ESTUDIANT) { // l'usuari es un estudiant
		 			u = new GestorEstudiant().getEstudiant(login);
	 			} else if (role == Usuari.TIPUS_USUARI_ADMINISTRADOR) { // l'usuari es un administrador
		 			u = new GestorAdministrador().getAdministrador(login);
	 			} else if (role == Usuari.TIPUS_USUARI_RESPONSABLEEVENTS) { // l'usuari es un responsable de proves
		 			u = new GestorResponsableEvents().getResponsableEvents(login);
	 			} else { // role desconegut
	 				throw new ExceptionServer(ExceptionServer.SERVER_DB_UNKNOWN_USER_ROLE);
	 			}
	 		} else throw new ExceptionServer(ExceptionServer.SERVER_DB_UNEXPECTED_ERROR);
		} catch (SQLException e) { ManageSQLException(e); } 
		finally { try { rs.close();	 st.close(); disconnect(); } catch(Exception e){ throw new ExceptionServer(ExceptionServer.SERVER_DB_UNEXPECTED_ERROR); } }
		return u;
	}

	
	public void updateUsuari(Usuari u) throws ExceptionServer {
		if (u == null) return;
		connect();
		try {
			char role = u.getTipusUsuari();
	 		if (role == Usuari.TIPUS_USUARI_ESTUDIANT && u instanceof Estudiante) { 	// l'usuari es un estudiant
	 			new GestorEstudiant().updateEstudiant((Estudiante)u);
 			} else if (role == Usuari.TIPUS_USUARI_ADMINISTRADOR &&  u instanceof Administrador) { // l'usuari es un administrador
	 			new GestorAdministrador().updateAdministrador((Administrador)u);
 			} else if (role == Usuari.TIPUS_USUARI_RESPONSABLEEVENTS && u instanceof ResponsableEvents) { // l'usuari es un responsable de proves
	 			new GestorResponsableEvents().updateResponsableEvents((ResponsableEvents)u);
 			} else { // role desconegut
 				throw new ExceptionServer(ExceptionServer.SERVER_DB_UNKNOWN_USER_ROLE); }
		} finally { disconnect(); }
	}

	
	public int insertUsuari(Usuari u) throws ExceptionServer {
		if (u == null) return -1;
		int seqId = -1;
		char role = u.getTipusUsuari();
 		if (role == Usuari.TIPUS_USUARI_ESTUDIANT && u instanceof Estudiante) { // l'usuari es un estudiant
 			seqId = new GestorEstudiant().insertEstudiant((Estudiante)u);
		} else if (role == Usuari.TIPUS_USUARI_ADMINISTRADOR &&  u instanceof Administrador) { // l'usuari es un administrador
 			seqId = new GestorAdministrador().insertAdministrador((Administrador)u);
		} else if (role == Usuari.TIPUS_USUARI_RESPONSABLEEVENTS && u instanceof ResponsableEvents) { // l'usuari es un responsable de proves
 			seqId = new GestorResponsableEvents().insertResponsableEvents((ResponsableEvents)u);
		} else { // role desconegut
			throw new ExceptionServer(ExceptionServer.SERVER_DB_UNKNOWN_USER_ROLE); }
 		return seqId;
	}
	
	// si realment es vol fer servir, ha de ser cercant per id intern, no per login
	public boolean existeixEnBD(Usuari u) throws ExceptionServer {
		if (u == null) return false;
		boolean exists = true;
		try { getUsuari(u.getIdUsuari()); } catch (ExceptionServer e) { if (e.getErrorCode().equals(ExceptionServer.SERVER_DB_USER_NOT_EXIST)) exists = false; else throw e; }
		return exists;
	}
	
	protected void	_updateusuari(Usuari u) throws ExceptionServer {
		connect();
//		if (! existeixEnBD(u)) throw new ExceptionServer("Server.DB.UserDoesNotExist");
		String update = "UPDATE usuari SET idusuari = ?, pwd = ?, email = ?, estatensistema = ?, tipusdocumentid = ?, document = ?, nom = ?, cognom1 = ?, cognom2 = ?, "
				+ "datamod = ?, databaixa = ? WHERE idintern = ?";
    	PreparedStatement st = null;
    	try {
	    	st = connection.prepareStatement(update,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
	 		st.setString(1,u.getIdUsuari()); st.setString(2,u.getPwd()); st.setString(3,u.getMail()); 
	 		String s = new Character(u.getEstatEnSistema()).toString(); st.setString(4,s);
	 		st.setString(5,u.getTipusDocumentId()); st.setString(6,u.getDocument()); 
	 		st.setString(7,u.getNom()); st.setString(8,u.getCognom1()); st.setString(9,u.getCognom2());
	 		java.util.Date d1 = u.getDataModificacio(); java.sql.Date d2 = (d1 == null? null : new java.sql.Date(d1.getTime())); st.setDate(10,d2);
	 		d1 = u.getDataEsborrat(); d2 = (d1 == null? null : new java.sql.Date(d1.getTime())); st.setDate(11,d2); st.setInt(12,u.getIdIntern());
	 		st.execute();
    	} catch (SQLException e) { ManageSQLException(e); } 
    	finally { disconnect(); }
	}
	
	protected int _insertusuari(Usuari u) throws ExceptionServer {
		connect();		
//		if (existeixEnBD(u)) throw new ExceptionServer(ExceptionServer.SERVER_DB_USER_ALREADY_EXIST);
		String insert = "INSERT INTO usuari(idusuari, pwd, email, estatensistema, tipusdocumentid, document, nom, cognom1, cognom2, dataalta, tipususuari) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
    	PreparedStatement st = null;
    	int internalId = -1;
    	try {
	    	st = connection.prepareStatement(insert,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
	 		st.setString(1,u.getIdUsuari()); st.setString(2,u.getPwd()); st.setString(3,u.getMail()); 
	 		String s = new Character(u.getEstatEnSistema()).toString(); st.setString(4,s);
	 		st.setString(5,u.getTipusDocumentId()); st.setString(6,u.getDocument()); 
	 		st.setString(7,u.getNom()); st.setString(8,u.getCognom1()); st.setString(9,u.getCognom2());
	 		java.util.Date d1 = u.getDataCreacio(); java.sql.Date d2 = (d1 == null? null : new java.sql.Date(d1.getTime())); st.setDate(10,d2);
	 		s = new Character(u.getTipusUsuari()).toString(); st.setString(11,s);
	 		st.execute();	 		
	 		// un cop feta la insercio hem de fer una consulta, per a obtenir el id intern que la base de dades ha assignat (es un autonumeric)
	 		internalId = _getUsuariInternalId(u.getIdUsuari());
    	} catch (SQLException e) { ManageSQLException(e); } 
    	finally { disconnect(); }
    	u.setIdIntern(internalId);
		return internalId;
	}
	
	protected int _getUsuariInternalId(String login) throws ExceptionServer {
	 	Statement st = null; ResultSet rs = null; int internalId = -1;
		connect();
		try {
			// Estem suposant que el login tambe es identificador: es a dir no hi ha dos usuaris amb el mateix login
  		    String query = "SELECT idintern FROM usuari WHERE idusuari = '" + login + "'";
		 	st = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
		 	rs = st.executeQuery(query);	
			if (rs.next()) {
	 			internalId = rs.getInt(1);
	 		} else throw new ExceptionServer(ExceptionServer.SERVER_DB_UNEXPECTED_ERROR);
		} catch (SQLException e) { ManageSQLException(e); } 
		finally { try { rs.close(); st.close(); disconnect(); } catch(Exception e){ throw new ExceptionServer(ExceptionServer.SERVER_DB_UNEXPECTED_ERROR); }  }
		return internalId;
	}
	
	public Vector<Usuari> getLlistaUsuaris(Estudiante criteriCerca) throws ExceptionServer {
	 	Statement st = null; ResultSet rs = null; Vector<Usuari> v = new Vector<Usuari>();
		connect();
		String select = "SELECT idintern, idusuari, tipusdocumentid, document, nom, cognom1, cognom2 ";
		String from = "FROM usuari ";
		String where = "WHERE true ";
		String orderby = "ORDER BY idintern";
		try {
			if (criteriCerca.getIdIntern() != null) where += "AND idintern = '" + criteriCerca.getIdIntern() + "' ";
	 		if (criteriCerca.getIdUsuari() != null && !"".equals(criteriCerca.getIdUsuari())) where += "AND idusuari = '" + escape(criteriCerca.getIdUsuari()) + "' "; 
	 		if (criteriCerca.getPwd() != null && !"".equals(criteriCerca.getPwd())) where += "AND pwd = '" + escape(criteriCerca.getPwd()) + "' "; 
	 		if (criteriCerca.getMail() != null && !"".equals(criteriCerca.getMail())) where += "AND email = '" + escape(criteriCerca.getMail()) + "' ";
	 		char c = criteriCerca.getTipusUsuari();
	 		if ((c == 'A') || (c == 'E') || (c == 'R')) where += "AND tipususuari = '" + c + "' "; 
	 		if (criteriCerca.getTipusDocumentId() != null && !"".equals(criteriCerca.getTipusDocumentId())) where += "AND tipusdocumentid = '" + escape(criteriCerca.getTipusDocumentId()) + "' "; 
	 		if (criteriCerca.getDocument() != null && !"".equals(criteriCerca.getDocument())) where += "AND document = '" + escape(criteriCerca.getDocument()) + "' "; 
	 		if (criteriCerca.getNom() != null && !"".equals(criteriCerca.getNom())) where += "AND nom = '" + escape(criteriCerca.getNom()) + "' "; 
	 		if (criteriCerca.getCognom1() != null && !"".equals(criteriCerca.getCognom1())) where += "AND cognom1 = '" + escape(criteriCerca.getCognom1()) + "' "; 
	 		if (criteriCerca.getCognom2() != null && !"".equals(criteriCerca.getCognom2())) where += "AND cognom2 = '" + escape(criteriCerca.getCognom2()) + "' ";
	 		if (criteriCerca.getUniversitat() != null && !"".equals(criteriCerca.getUniversitat())) {
	 			from += ", estudiant ";
	 			where += "AND idestudiant = idintern AND universitat = '" + criteriCerca.getUniversitat() + "' ";
	 		}
	 		SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
	 		if (criteriCerca.getDataCreacio() != null) where += "AND dataalta = to_date('" + sdf.format(criteriCerca.getDataCreacio()) + "', 'dd-mm-yyyy') ";
	 		if (criteriCerca.getDataModificacio() != null) where += "AND datamod = to_date('" + sdf.format(criteriCerca.getDataModificacio()) + "', 'dd-mm-yyyy') ";
	 		if (criteriCerca.getDataEsborrat() != null) where += "AND databaixa = to_date('" + sdf.format(criteriCerca.getDataEsborrat()) + "', 'dd-mm-yyyy') ";
		 	st = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
		 	rs = st.executeQuery(select + from + where + orderby);
			while (rs.next()) {
				Usuari u = new Usuari();
				u.setIdIntern(rs.getInt(1)); u.setIdUsuari(rs.getString(2)); u.setTipusDocumentId(rs.getString(3)); u.setDocument(rs.getString(4)); 
				u.setNom(rs.getString(5)); u.setCognom1(rs.getString(6)); u.setCognom2(rs.getString(7));
				v.add(u);
			}
		} catch (SQLException e) { ManageSQLException(e); }
		return v;
	}
	
	private String escape(String s) {
		return s.replaceAll("'", "''");
	}
}
	
